using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Data;
using System.Windows.Forms;
using System.Xml.Schema;
using System.IO;
using System.Drawing;
using OpenComposite.Base;
using OpenComposite.Repository.Properties;
using OpenComposite.Base.Collections;
using OpenComposite.EII.RepositoryUIs;
using System.Xml.Serialization;

namespace OpenComposite.EII.Repository
{
	[RepositoryItem(ItemType.KPI, "key_performance_indicators", "kpi_id")]
	public class KeyPerformanceIndicator : RepositoryItemBase
	{
		#region Initialization
		/// <summary>
		/// Initializes a new instance of the <see cref="KeyPerformanceIndicator"/> class.
		/// </summary>
		public KeyPerformanceIndicator()
			: base("kpi_id", "kpi_nm", "kpi_desc", "kpi_ntext", Resources.sNewKPI)
		{
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="KeyPerformanceIndicator"/> class.
		/// </summary>
		/// <param name="bCreateNew">if set to <c>true</c> [b create new].</param>
		public KeyPerformanceIndicator(bool bCreateNew)
			: this()
		{
			if ( bCreateNew ) {
				this.CreateNew();
			}
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="KeyPerformanceIndicator"/> class.
		/// </summary>
		/// <param name="id">The id.</param>
		public KeyPerformanceIndicator(int id)
			: this()
		{
			this.Load(id);
		}
		#endregion

		#region Properties

		#region Override
		/// <summary>
		/// Gets the image.
		/// </summary>
		/// <value>The image.</value>
		public override Image Image
		{
			get { return Resources.png_kpi; }
		}

		/// <summary>
		/// Gets the type of the repository item.
		/// </summary>
		/// <value>The type of the repository item.</value>
		public override ItemType RepositoryItemType
		{
			get { return ItemType.KPI; }
		}
		/// <summary>
		/// Gets the name of the repository item type.
		/// </summary>
		/// <value>The name of the repository item type.</value>
		public override string RepositoryItemTypeName
		{
			get { return "KPI"; }
		}
		/// <summary>
		/// Gets the repository item type description.
		/// </summary>
		/// <value>The repository item type description.</value>
		public override string RepositoryItemTypeDescription
		{
			get { return ""; }
		}

		/// <summary>
		/// Gets the name of the table.
		/// </summary>
		/// <value>The name of the table.</value>
		public override string TableName
		{
			get { return "key_performance_indicators"; }
		}
		private static List<ItemType> _LISTALLOWED = new List<ItemType>();
		/// <summary>
		/// Gets the allowed child types.
		/// </summary>
		/// <value>The allowed child types.</value>
		public override List<ItemType> AllowedChildTypes
		{
			get { return _LISTALLOWED; }
		}


		/// <summary>
		/// Gets the display text.
		/// </summary>
		/// <value>The display text.</value>
		public override string Display
		{
			get
			{
				return this.Name;
			}
		}

		/// <summary>
		/// Gets the selected image.
		/// </summary>
		/// <value>The selected image.</value>
		public override Image SelectedImage
		{
			get { return Resources.png_kpi; }
		}

		/// <summary>
		/// Gets the image key.
		/// </summary>
		/// <value>The image key.</value>
		public override string ImageKey
		{
			get { return "kpi"; }
		}

		/// <summary>
		/// Gets the selected image key.
		/// </summary>
		/// <value>The selected image key.</value>
		public override string SelectedImageKey
		{
			get { return this.ImageKey; }
		}

		#endregion

		/// <summary>
		/// Gets or sets the domain id.
		/// </summary>
		/// <value>The domain id.</value>
		public int DomainId
		{
			get { return base.getInt("domain_id", 0); }
			set { base.setValue("DomainId", "domain_id", value); }
		}
		/// <summary>
		/// Gets or sets the organisation id.
		/// </summary>
		/// <value>The organisation id.</value>
		public int OrganisationId
		{
			get { return base.getInt("org_id", 0); }
			set { base.setValue("OrganisationId", "org_id", value); }
		}

		/// <summary>
		/// Gets or sets the type.
		/// </summary>
		/// <value>The type.</value>
		public string Type
		{
			get { return getString("kpi_type", ""); }
			set { setValue("Type", "kpi_type", value); }
		}
		//public string Units
		//{
		//    get { return getString("kpi_units", ""); }
		//    set { setValue("Units", "kpi_units", value); }
		//}
		//public BindingListEx<string> UnitList
		//{
		//    get { return new BindingListEx<string>(Units.Split(UnitSeperator)); }
		//}
		/// <summary>
		/// <see cref="T:System.Char"/> to seperate serialized unit list.
		/// </summary>
		internal const char UnitSeperator = ';';
		/// <summary>
		/// Gets or sets the type of the data.
		/// </summary>
		/// <value>The type of the data.</value>
		public string DataType
		{
			get { return getString("kpi_datatype", ""); }
			set { setValue("DataType", "kpi_datatype", value); }
		}
		/// <summary>
		/// Gets or sets the type of the calculation.
		/// </summary>
		/// <value>The type of the calculation.</value>
		public string CalculationType
		{
			get { return getString("kpi_calculationtype", ""); }
			set { setValue("CalculationType", "kpi_calculationtype", string.IsNullOrEmpty(value) ? "" : value[0].ToString()); }
		}
		/// <summary>
		/// Gets or sets the null value.
		/// </summary>
		/// <value>The null value.</value>
		public object NullValue
		{
			get { return getString("kpi_nullvalue", ""); }
			set { setValue("NullValue", "kpi_nullvalue", value == null ? "0.0" : value); }
		}
		private KPIExtendedProperties _properties = null;
		/// <summary>
		/// Gets or sets the extended properties.
		/// </summary>
		/// <value>The extended properties.</value>
		public KPIExtendedProperties ExtendedProperties
		{
			get
			{
				if ( _properties == null ) {
					_properties = base.getXmlSerializedObject<KPIExtendedProperties>("kpi_ntext");
					if ( _properties == null ) _properties = new KPIExtendedProperties();
				}
				return _properties;
			}
			set { _properties = value; }
		}
		/// <summary>
		/// Gets the base unit.
		/// </summary>
		/// <value>The base unit.</value>
		public KpiUnit BaseUnit
		{
			get
			{
				foreach ( KpiUnit unit in this.ExtendedProperties.Units ) {
					if ( unit.IsBaseUnit ) return unit;
				}
				return null;
			}
		}
		/// <summary>
		/// Gets the kpi unit.
		/// </summary>
		/// <param name="name">The name.</param>
		/// <returns></returns>
		public KpiUnit GetKpiUnit(string name)
		{
			if ( string.IsNullOrEmpty(name) ) return this.BaseUnit;
			foreach ( KpiUnit unit in this.ExtendedProperties.Units ) {
				if ( unit.Name == name ) return unit;
			}
			return null;
		}
		/// <summary>
		/// Gets the metrics.
		/// </summary>
		/// <returns></returns>
		public BindingListEx<KPIMetric> GetMetrics()
		{
			return Global.Data.GetMetrics(this.ID);
		}

		#endregion

		#region Methods

		#region Override
		/// <summary>
		/// Sets the default values.
		/// </summary>
		protected override void SetDefaultValues()
		{
			this.Type = "";
			base.SetDefaultValues();
		}
		/// <summary>
		/// Gets the icon.
		/// </summary>
		/// <returns></returns>
		public override Icon GetIcon()
		{
			Bitmap bmp = new Bitmap(this.Image);
			bmp.MakeTransparent(Color.Magenta);
			return Icon.FromHandle(bmp.GetHicon());
		}
		/// <summary>
		/// Shows the new item form.
		/// </summary>
		/// <param name="idRepository">The repository ID.</param>
		/// <param name="bAllowContinue">if set to <c>true</c> to allow save and continue.</param>
		/// <param name="parentItem">The parent item.</param>
		/// <param name="idDomain">The domain ID.</param>
		/// <param name="parentItemNew">The new parent item.</param>
		/// <returns></returns>
		public override DialogResult ShowNewItemForm(int idRepository, bool bAllowContinue, IRepositoryItem parentItem, ref int idDomain, out IRepositoryItem parentItemNew)
		{
			FormCreateNewKPI dlg = new FormCreateNewKPI(this, bAllowContinue);
			dlg.DomainID = idDomain;
			dlg.ParentItem = parentItem;
			DialogResult result = dlg.ShowDialog();
			if ( result == DialogResult.OK || result == DialogResult.Retry ) {
				idDomain = dlg.DomainID;
				parentItemNew = dlg.NewParentItem;
			} else {
				idDomain = 0;
				parentItemNew = null;
			}
			return result;
		}
		/// <summary>
		/// Shows the edit item form.
		/// </summary>
		/// <returns></returns>
		public DialogResult ShowEditItemForm()
		{
			FormCreateNewKPI dlg = new FormCreateNewKPI(this, false);
			DialogResult result = dlg.ShowDialog();
			if ( result == DialogResult.OK || result == DialogResult.Retry ) {
			} else {
			}
			return result;
		}
		/// <summary>
		/// Saves this instance.
		/// </summary>
		/// <returns></returns>
		public override bool Save()
		{
			row["kpi_nullvalue"] = "0";
			if ( _properties != null ) {
				XmlSerializer serializer = new XmlSerializer(typeof(KPIExtendedProperties));
				StringBuilder sb = new StringBuilder();
				XmlWriterSettings settings = new XmlWriterSettings();
				using ( XmlWriter xw = XmlWriter.Create(sb, settings) ) {
					serializer.Serialize(xw, _properties);
				}
				XmlDocument xd = new XmlDocument();
				xd.InnerXml = sb.ToString();
				base.setXmlDocument("ExtendedProperties", "kpi_ntext", xd);
			}
			return base.Save();
		}
		/// <summary>
		/// Copies this instance.
		/// </summary>
		/// <param name="deep"><c>true</c> to recursively copy the item and all subitems;
		/// <c>false</c> to copy only the item itself.</param>
		/// <returns>The copied item.</returns>
		public override IRepositoryItem Copy(bool deep)
		{
			KeyPerformanceIndicator copy = new KeyPerformanceIndicator(true);
			copy.InitializeServiceProvider(this);
			this.CopyDataRowToTarget(copy);
			return copy;
		}
		#endregion

		#endregion

	}

	[Serializable]
	public class KPIExtendedProperties
	{
		#region public KPIExtendedProperties()

		/// <summary>
		/// Initializes a new instance of the <see cref="T:KPIExtendedProperties"/> class.
		/// </summary>
		public KPIExtendedProperties()
		{
			Units = new BindingListEx<KpiUnit>();
		}

		#endregion

		/// <summary>
		/// Gets or sets the units.
		/// </summary>
		/// <value>The units.</value>
		[XmlIgnore]
		public BindingListEx<KpiUnit> Units { get; private set; }
		/// <summary>
		/// Gets or sets the units array.
		/// </summary>
		/// <value>The units array.</value>
		public KpiUnit[] UnitsArray
		{
			get { return Units.ToArray(); }
			set
			{
				Units.Clear();
				Units.AddRange(value);
			}
		}
	}

	[Serializable]
	public class KpiUnit
	{
		#region public KpiUnit()

		/// <summary>
		/// Initializes a new instance of the <see cref="T:KpiUnit"/> class.
		/// </summary>
		public KpiUnit()
		{
			this.IsBaseUnit = false;
			this.OperationValue = 1;
			this.OperationSign = "*";
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="T:KpiUnit"/> class.
		/// </summary>
		/// <param name="name">The name.</param>
		public KpiUnit(string name)
			: this()
		{
			this.Name = name;
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="T:KpiUnit"/> class.
		/// </summary>
		/// <param name="name">The name.</param>
		public KpiUnit(string name, bool isBase)
			: this(name)
		{
			this.IsBaseUnit = isBase;
		}

		#endregion

		/// <summary>
		/// Returns a <see cref="System.String"/> that represents this instance.
		/// </summary>
		/// <returns>
		/// A <see cref="System.String"/> that represents this instance.
		/// </returns>
		public override string ToString()
		{
			return Name;
		}

		/// <summary>
		/// Gets or sets a value indicating whether this instance is base unit.
		/// </summary>
		/// <value>
		/// 	<c>true</c> if this instance is base unit; otherwise, <c>false</c>.
		/// </value>
		public bool IsBaseUnit { get; set; }
		/// <summary>
		/// Gets or sets the name.
		/// </summary>
		/// <value>The name.</value>
		public string Name { get; set; }
		/// <summary>
		/// Gets or sets the operation sign.
		/// </summary>
		/// <value>The operation sign.</value>
		public string OperationSign { get; set; }
		/// <summary>
		/// Gets or sets the operation value.
		/// </summary>
		/// <value>The operation value.</value>
		public decimal OperationValue { get; set; }
	}
}